#include "EventloopProxy.h"
#include "Eventloop.h"
#include "IOchannelProxy.h"
#include "Poller.h"
#include "log/Logger.h"
#include "utility/assertion.h"

EventloopProxy::EventloopProxy(Eventloop &loop):
    _activeChannels{},
    _currentActiveChannel{},
    _poller{Poller::DEFAULT(loop)},
    _loop{loop},
    _handlingEvent{false} {}

EventloopProxy::~EventloopProxy() = default;

void EventloopProxy::poll_event() {
    _activeChannels.clear();
    const auto pollTimestamp = _poller->poll(POLL_TIMEOUT_MS, _activeChannels);
    _handlingEvent = true;
    for (auto &x : _activeChannels) {
        LOG_VERBOSE << '{' << x.get().return_events_string() << "} of " 
                    << _activeChannels.size();
        _currentActiveChannel = x;
        _currentActiveChannel.value().get().handle_event(pollTimestamp);
    }
    _currentActiveChannel.reset();
    _handlingEvent = false;

}

bool EventloopProxy::has(const IOchannelProxy &channel) const {
    assert(channel.eventloopProxy() == *this);
    _loop.ASSERT_IN_THIS_THREAD();
    return _poller->has(channel);
    
}

void EventloopProxy::remove(IOchannelProxy &channel) const {
     assert(channel.eventloopProxy() == *this);
    _loop.ASSERT_IN_THIS_THREAD();
    if (_handlingEvent) {
        assert(_currentActiveChannel.value().get() == channel ||
               std::find_if(_activeChannels.cbegin(), _activeChannels.cend(),
                    [&channel](const IOchannelProxyRef &ref){
                        return ref.get() == channel; 
                    }) == _activeChannels.end());
    }
    _poller->remove(channel);
}

void EventloopProxy::update(IOchannelProxy &channel) const {
     assert(channel.eventloopProxy() == *this);
    _loop.ASSERT_IN_THIS_THREAD();
    _poller->update(channel);
}

